"""
文件名: categories.py
描述: 分类管理API路由

本模块包含以下主要功能：
1. 分类CRUD操作
2. 频道分类关联管理
3. 分类排序和批量操作
4. 分类统计信息

依赖模块:
   - fastapi: Web框架路由
   - services: 分类服务
   - models: 数据模型

使用示例:
   >>> GET /categories - 获取用户分类列表
   >>> POST /categories - 创建新分类
   >>> PUT /categories/{id} - 更新分类
   >>> DELETE /categories/{id} - 删除分类

注意事项:
   - 用户只能操作自己的分类
   - 默认分类不能删除
   - 分类名称要唯一
   - 支持批量操作

作者: AI助手
创建日期: 2024-06-27
最后修改: 2024-06-27
版本: 1.0.0
"""

from typing import List, Dict, Any
import uuid

from fastapi import APIRouter, Depends, HTTPException, status
from pydantic import BaseModel

from src.api.dependencies import (
    get_current_user,
    get_category_service,
    get_pagination_params,
)
from src.core.logger import get_logger
from src.models.user import User
from src.models.category import (
    CategoryInDB,
    CategoryCreate,
    CategoryUpdate,
    CategorySummary,
)
from src.services.category_service import CategoryService
from src.utils.exceptions import (
    ValidationException,
    AuthorizationException,
)

logger = get_logger(__name__)

router = APIRouter()


class CategoryCreateRequest(BaseModel):
    """分类创建请求模型"""
    name: str
    description: str = None
    icon: str = None
    color: str = None
    sort_order: int = 0


class CategoryUpdateRequest(BaseModel):
    """分类更新请求模型"""
    name: str = None
    description: str = None
    icon: str = None
    color: str = None
    sort_order: int = None
    is_active: bool = None


class BatchAssignRequest(BaseModel):
    """批量分配请求模型"""
    channel_ids: List[uuid.UUID]


@router.get("", response_model=List[CategorySummary], summary="获取用户分类列表")
async def get_user_categories(
    current_user: User = Depends(get_current_user),
    category_service: CategoryService = Depends(get_category_service),
    only_active: bool = True,
) -> List[CategorySummary]:
    """
    获取当前用户的所有分类
    
    Args:
        only_active: 是否只返回激活的分类
        
    Returns:
        List[CategorySummary]: 分类摘要列表
    """
    try:
        categories = await category_service.get_user_categories(
            current_user.id,
            include_channel_count=True,
            only_active=only_active,
        )
        
        # 转换为摘要格式
        summaries = []
        for category in categories:
            summary = CategorySummary(
                id=category.id,
                name=category.name,
                icon=category.icon,
                color=category.color,
                channel_count=category.channel_count,
                is_default=category.is_default,
                sort_order=category.sort_order,
            )
            summaries.append(summary)
        
        return summaries
        
    except Exception as e:
        logger.error(f"获取用户分类失败: {e}", user_id=str(current_user.id))
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="获取分类列表失败"
        )


@router.post("", response_model=CategoryInDB, summary="创建新分类")
async def create_category(
    category_data: CategoryCreateRequest,
    current_user: User = Depends(get_current_user),
    category_service: CategoryService = Depends(get_category_service),
) -> CategoryInDB:
    """
    创建新的频道分类
    
    Args:
        category_data: 分类创建数据
        
    Returns:
        CategoryInDB: 创建的分类
    """
    try:
        # 创建分类数据
        create_data = CategoryCreate(
            user_id=current_user.id,
            name=category_data.name,
            description=category_data.description,
            icon=category_data.icon,
            color=category_data.color,
            sort_order=category_data.sort_order,
        )
        
        category = await category_service.create_category(current_user.id, create_data)
        
        logger.info(f"分类创建成功", category_id=str(category.id), name=category.name)
        return category
        
    except ValidationException as e:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=str(e)
        )
    except Exception as e:
        logger.error(f"创建分类失败: {e}", user_id=str(current_user.id))
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="创建分类失败"
        )


@router.get("/{category_id}", response_model=CategoryInDB, summary="获取分类详情")
async def get_category(
    category_id: uuid.UUID,
    current_user: User = Depends(get_current_user),
    category_service: CategoryService = Depends(get_category_service),
) -> CategoryInDB:
    """
    获取指定分类的详细信息
    
    Args:
        category_id: 分类ID
        
    Returns:
        CategoryInDB: 分类详细信息
    """
    try:
        category = await category_service.get_category_by_id(category_id, current_user.id)
        if not category:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail="分类不存在"
            )
        
        return category
        
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"获取分类详情失败: {e}", category_id=str(category_id))
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="获取分类详情失败"
        )


@router.put("/{category_id}", response_model=CategoryInDB, summary="更新分类")
async def update_category(
    category_id: uuid.UUID,
    category_data: CategoryUpdateRequest,
    current_user: User = Depends(get_current_user),
    category_service: CategoryService = Depends(get_category_service),
) -> CategoryInDB:
    """
    更新指定分类的信息
    
    Args:
        category_id: 分类ID
        category_data: 分类更新数据
        
    Returns:
        CategoryInDB: 更新后的分类
    """
    try:
        # 创建更新数据
        update_data = CategoryUpdate(
            name=category_data.name,
            description=category_data.description,
            icon=category_data.icon,
            color=category_data.color,
            sort_order=category_data.sort_order,
            is_active=category_data.is_active,
        )
        
        category = await category_service.update_category(
            category_id, current_user.id, update_data
        )
        
        if not category:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail="分类不存在"
            )
        
        logger.info(f"分类更新成功", category_id=str(category_id))
        return category
        
    except ValidationException as e:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=str(e)
        )
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"更新分类失败: {e}", category_id=str(category_id))
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="更新分类失败"
        )


@router.delete("/{category_id}", summary="删除分类")
async def delete_category(
    category_id: uuid.UUID,
    current_user: User = Depends(get_current_user),
    category_service: CategoryService = Depends(get_category_service),
    force: bool = False,
) -> Dict[str, str]:
    """
    删除指定分类
    
    Args:
        category_id: 分类ID
        force: 是否强制删除（用于删除默认分类）
        
    Returns:
        Dict[str, str]: 删除结果
    """
    try:
        success = await category_service.delete_category(
            category_id, current_user.id, force
        )
        
        if not success:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail="分类不存在"
            )
        
        logger.info(f"分类删除成功", category_id=str(category_id))
        return {"message": "分类删除成功"}
        
    except ValidationException as e:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=str(e)
        )
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"删除分类失败: {e}", category_id=str(category_id))
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="删除分类失败"
        )


@router.get("/{category_id}/channels", summary="获取分类下的频道")
async def get_category_channels(
    category_id: uuid.UUID,
    current_user: User = Depends(get_current_user),
    category_service: CategoryService = Depends(get_category_service),
    pagination: Dict[str, int] = Depends(get_pagination_params),
) -> Dict[str, Any]:
    """
    获取指定分类下的频道列表
    
    Args:
        category_id: 分类ID
        pagination: 分页参数
        
    Returns:
        Dict[str, Any]: 频道列表和分页信息
    """
    try:
        channels, total = await category_service.get_category_channels(
            category_id,
            current_user.id,
            limit=pagination["limit"],
            offset=pagination["offset"],
        )
        
        return {
            "channels": channels,
            "total": total,
            "page": pagination["page"],
            "size": pagination["size"],
            "pages": (total + pagination["size"] - 1) // pagination["size"],
        }
        
    except AuthorizationException as e:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail=str(e)
        )
    except Exception as e:
        logger.error(f"获取分类频道失败: {e}", category_id=str(category_id))
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="获取频道列表失败"
        )


@router.post("/{category_id}/channels/{channel_id}", summary="将频道添加到分类")
async def add_channel_to_category(
    category_id: uuid.UUID,
    channel_id: uuid.UUID,
    current_user: User = Depends(get_current_user),
    category_service: CategoryService = Depends(get_category_service),
) -> Dict[str, str]:
    """
    将频道添加到指定分类
    
    Args:
        category_id: 分类ID
        channel_id: 频道ID
        
    Returns:
        Dict[str, str]: 操作结果
    """
    try:
        success = await category_service.assign_channel_to_category(
            channel_id, category_id, current_user.id
        )
        
        if success:
            logger.info(f"频道添加到分类成功", category_id=str(category_id), channel_id=str(channel_id))
            return {"message": "频道添加成功"}
        else:
            return {"message": "频道已在该分类中"}
        
    except (ValidationException, AuthorizationException) as e:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=str(e)
        )
    except Exception as e:
        logger.error(f"添加频道到分类失败: {e}", category_id=str(category_id), channel_id=str(channel_id))
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="添加频道失败"
        )


@router.delete("/{category_id}/channels/{channel_id}", summary="从分类中移除频道")
async def remove_channel_from_category(
    category_id: uuid.UUID,
    channel_id: uuid.UUID,
    current_user: User = Depends(get_current_user),
    category_service: CategoryService = Depends(get_category_service),
) -> Dict[str, str]:
    """
    从指定分类中移除频道
    
    Args:
        category_id: 分类ID
        channel_id: 频道ID
        
    Returns:
        Dict[str, str]: 操作结果
    """
    try:
        success = await category_service.remove_channel_from_category(
            channel_id, category_id, current_user.id
        )
        
        if success:
            logger.info(f"频道从分类移除成功", category_id=str(category_id), channel_id=str(channel_id))
            return {"message": "频道移除成功"}
        else:
            return {"message": "频道不在该分类中"}
        
    except AuthorizationException as e:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail=str(e)
        )
    except Exception as e:
        logger.error(f"从分类移除频道失败: {e}", category_id=str(category_id), channel_id=str(channel_id))
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="移除频道失败"
        )


@router.post("/{category_id}/channels/batch", summary="批量添加频道到分类")
async def batch_add_channels_to_category(
    category_id: uuid.UUID,
    request: BatchAssignRequest,
    current_user: User = Depends(get_current_user),
    category_service: CategoryService = Depends(get_category_service),
) -> Dict[str, Any]:
    """
    批量将频道添加到指定分类
    
    Args:
        category_id: 分类ID
        request: 批量分配请求
        
    Returns:
        Dict[str, Any]: 批量操作结果
    """
    try:
        stats = await category_service.batch_assign_channels(
            request.channel_ids, category_id, current_user.id
        )
        
        logger.info(f"批量添加频道到分类完成", category_id=str(category_id), stats=stats)
        
        return {
            "message": "批量操作完成",
            "stats": stats,
        }
        
    except AuthorizationException as e:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail=str(e)
        )
    except Exception as e:
        logger.error(f"批量添加频道失败: {e}", category_id=str(category_id))
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="批量操作失败"
        )